home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 February / EnigmA AMIGA RUN 15 (1997)(G.R. Edizioni)(IT)[!][issue 1997-02][PLANET CD V].iso / enigma / earcd / varie / uae-0_64.lha / uae-0.6.4 / src / gfxutil.c < prev    next >
C/C++ Source or Header  |  1996-08-14  |  9KB  |  415 lines

  1.  /* 
  2.   * UAE - The Un*x Amiga Emulator
  3.   * 
  4.   * Common code needed by all the various graphics systems.
  5.   * 
  6.   * (c) 1996 Bernd Schmidt, Ed Hanway, Samuel Devulder
  7.   */
  8.  
  9. #include "sysconfig.h"
  10. #include "sysdeps.h"
  11.  
  12. #include "config.h"
  13. #include "options.h"
  14. #include "memory.h"
  15. #include "custom.h"
  16. #include "newcpu.h"
  17. #include "keyboard.h"
  18. #include "xwin.h"
  19. #include "keybuf.h"
  20.  
  21. #define    RED     0
  22. #define    GRN    1
  23. #define    BLU    2
  24.  
  25. /*
  26.  * dither matrix
  27.  */
  28. static UBYTE dither[4][4] =
  29. {
  30.   {0,8,2,10},
  31.   {12,4,14,6},
  32.   {3,11,1,9},
  33.   {14 /* 15 */,7,13,5}
  34. };
  35.  
  36. unsigned long doMask(int p, int bits, int shift)
  37. {
  38.     /* p is a value from 0 to 15 (Amiga color value)
  39.      * scale to 0..255, shift to align msb with mask, and apply mask */
  40.  
  41.     unsigned long val = p * 0x11111111UL;
  42.     val >>= (32 - bits);
  43.     val <<= shift;
  44.  
  45.     return val;
  46. }
  47.  
  48. void alloc_colors64k(int rw, int gw, int bw, int rs, int gs, int bs)
  49. {
  50.     int i;
  51.     for(i=0; i<4096; i++) {
  52.     int r = i >> 8;
  53.     int g = (i >> 4) & 0xF;
  54.     int b = i & 0xF;
  55.     xcolors[i] = doMask(r, rw, rs) | doMask(g, gw, gs) | doMask(b, bw, bs);
  56.     }
  57. }
  58.  
  59. static int allocated[4096];
  60.  
  61. void alloc_colors256(allocfunc_type allocfunc)
  62. {
  63.     int nb_cols[3]; /* r,g,b */
  64.     int maxcol = 256;
  65.     int i,j,k,l,t;
  66.     int diff[4096];
  67.  
  68.     xcolnr *map;
  69.     
  70.     map = (xcolnr *)malloc(sizeof(xcolnr) * maxcol);
  71.     
  72.     /*
  73.      * compute #cols per components
  74.      */
  75.     for(i = 1; i*i*i <= maxcol; ++i)
  76.     ;
  77.     --i;
  78.  
  79.     nb_cols[RED] = i;
  80.     nb_cols[GRN] = i;
  81.     nb_cols[BLU] = i;
  82.  
  83.     /*
  84.      * set the colormap
  85.      */
  86.     l=0;
  87.     for(i = 0; i < nb_cols[RED]; ++i) {
  88.     int r = (i * 15 + (nb_cols[RED] - 1)/2) / (nb_cols[RED] - 1);
  89.     for(j = 0; j < nb_cols[GRN]; ++j) {
  90.         int g = (j * 15 + (nb_cols[GRN] - 1)/2) / (nb_cols[GRN] - 1);
  91.         for(k = 0; k < nb_cols[BLU]; ++k) { 
  92.         int b = (k * 15 + (nb_cols[BLU] - 1)/2) / (nb_cols[BLU] - 1);
  93.         int result;
  94.         result = allocfunc(r, g, b, map + l);
  95.         l++;
  96.         }
  97.     }
  98.     }
  99. /*    printf("%d color(s) lost\n",maxcol - l);*/
  100.  
  101.     /*
  102.      * for each component compute the mapping
  103.      */
  104.     {
  105.     int diffr, diffg, diffb, maxdiff = 0, won = 0, lost;
  106.     int r, d = 8;
  107.     for(r=0; r<16; ++r) {
  108.         int cr, g, q;
  109.       
  110.         k  = nb_cols[RED]-1;
  111.         cr = (r * k) / 15;
  112.         q  = (r * k) % 15;
  113.         if(q > d && cr < k) ++cr;
  114.         diffr = abs(cr*k-r);
  115.         for(g=0; g<16; ++g) {
  116.         int cg, b;
  117.           
  118.         k  = nb_cols[GRN]-1;
  119.         cg = (g * k) / 15;
  120.         q  = (g * k) % 15;
  121.         if(q > d && cg < k) ++cg;
  122.         diffg = abs(cg*k-g);
  123.         for(b=0; b<16; ++b) {
  124.             int cb, rgb = (r<<8) | (g<<4) | b;
  125.  
  126.             k  = nb_cols[BLU]-1;
  127.             cb = (b * k) / 15;
  128.             q  = (b * k) % 15;
  129.             if(q > d && cb < k) ++cb;
  130.             diffb = abs(cb*k-b);
  131.             xcolors[rgb] = map[(cr*nb_cols[GRN]+cg)*nb_cols[BLU]+cb];
  132.             diff[rgb] = diffr+diffg+diffb;
  133.             if (diff[rgb] > maxdiff)
  134.             maxdiff = diff[rgb];
  135.         }
  136.         }
  137.     }
  138.     while (maxdiff > 0 && l < maxcol) {
  139.         int newmaxdiff = 0;
  140.         lost = 0; won++;
  141.         for(r = 15; r >= 0; r--) {
  142.         int cr, g, q;
  143.       
  144.         for(g = 15; g >= 0; g--) {
  145.             int cg, b;
  146.           
  147.             for(b = 15; b >= 0; b--) {
  148.             int cb, rgb = (r<<8) | (g<<4) | b;
  149.  
  150.             if (diff[rgb] == maxdiff) {
  151.                 int result;
  152.             
  153.                 if (l >= maxcol)
  154.                 lost++;
  155.                 else {
  156.                 result = allocfunc(r, g, b, xcolors + rgb);
  157.                 l++;
  158.                 }
  159.                 diff[rgb] = 0;
  160.             } else if (diff[rgb] > newmaxdiff)
  161.                 newmaxdiff = diff[rgb];
  162.             
  163.             }
  164.         }
  165.         }
  166.         maxdiff = newmaxdiff;
  167.     }
  168. /*    printf("%d color(s) lost, %d stages won\n",lost, won);*/
  169.     }
  170.     free (map);
  171. }
  172.  
  173. /*
  174.  * This dithering process works by letting UAE run internaly in 12bit
  175.  * mode and doing the dithering on the fly when rendering to the display.
  176.  * The dithering algorithm is quite fast but uses lot of memory (4*8*2^12 =
  177.  * 128Kb). I don't think that is a trouble right now, but when UAE will 
  178.  * emulate AGA and work internaly in 24bit mode, that dithering algorithm
  179.  * will need 4*8*2^24 = 512Mb. Obviously that fast algorithm will not be
  180.  * tractable. However, we could then use an other algorithm, slower, but 
  181.  * far more reasonable (I am thinking about the one that is used in DJPEG).
  182.  */
  183.  
  184. UBYTE cidx[4][8*4096]; /* fast, but memory hungry =:-( */
  185.  
  186. /*
  187.  * Compute dithering structures
  188.  */
  189. void setup_greydither(int bits, allocfunc_type allocfunc)
  190. {
  191.     int i,j,k,l,t;
  192.     int maxcol = 1 << bits;
  193.     xcolnr *map;
  194.     
  195.     for (i = 0; i < 4096; i++)
  196.     xcolors[i] = i;
  197.     
  198.     map = (xcolnr *)malloc(sizeof(xcolnr) * maxcol);
  199.  
  200.     /*
  201.      * set the colormap
  202.      */
  203.     for(i = 0; i < maxcol; ++i) {
  204.     int c, result;
  205.     c = (15 * i + (maxcol-1)/2) / (maxcol - 1);
  206.         result = allocfunc(c, c, c, map + i);
  207.     /* @@@ check for errors */
  208.     }
  209.  
  210.     /*
  211.      * for each componant compute the mapping
  212.      */
  213.     for(i=0;i<4;++i) {
  214.     for(j=0;j<4;++j) {
  215.         int r, d = dither[i][j]*17;
  216.         for(r=0; r<16; ++r) {
  217.         int g;
  218.         for(g=0; g<16; ++g) {
  219.             int  b;
  220.             for(b=0; b<16; ++b) {
  221.             int rgb = (r<<8) | (g<<4) | b;
  222.             int c,p,q;
  223.             
  224.             c = (77  * r + 
  225.                  151 * g + 
  226.                  28  * b) / 15; /* c in 0..256 */
  227.             
  228.             k = maxcol-1;  
  229.             p = (c * k) / 256;
  230.             q = (c * k) % 256;
  231.             if(q / k > d / k && p < k) ++p;
  232.             cidx[i][rgb + (j+4)*4096] = 
  233.                 cidx[i][rgb + j*4096] = map[p];
  234.             }
  235.         }
  236.         }
  237.     }
  238.     }
  239.     free (map);
  240. }
  241.  
  242. void setup_dither(int bits, allocfunc_type allocfunc)
  243. {
  244.     int nb_cols[3]; /* r,g,b */
  245.     int maxcol = 1 << bits;
  246.     int i,j,k,l,t;
  247.  
  248.     xcolnr *map;
  249.     int *redvals, *grnvals, *bluvals;
  250.     
  251.     map = (xcolnr *)malloc(sizeof(xcolnr) * maxcol);
  252.  
  253.     for (i = 0; i < 4096; i++)
  254.     xcolors[i] = i;
  255.     
  256.     /*
  257.      * compute #cols per components
  258.      */
  259.     for(i = 1; i*i*i <= maxcol; ++i)
  260.     ;
  261.     --i;
  262.  
  263.     nb_cols[RED] = i;
  264.     nb_cols[GRN] = i;
  265.     nb_cols[BLU] = i;
  266.  
  267.     if(nb_cols[RED]*(++i)*nb_cols[BLU] <= maxcol) {
  268.     nb_cols[GRN] = i;
  269.     if((i)*nb_cols[GRN]*nb_cols[BLU] <= maxcol) nb_cols[RED] = i;
  270.     }
  271.  
  272.     redvals = (int *)malloc(sizeof(int) * maxcol);
  273.     grnvals = redvals + nb_cols[RED];
  274.     bluvals = grnvals + nb_cols[BLU];
  275.     /*
  276.      * set the colormap
  277.      */
  278.     l=0;
  279.     for(i = 0; i < nb_cols[RED]; ++i) {
  280.     int r = (i * 15 + (nb_cols[RED] - 1)/2) / (nb_cols[RED] - 1);
  281.     redvals[i] = r;
  282.     for(j = 0; j < nb_cols[GRN]; ++j) {
  283.         int g = (j * 15 + (nb_cols[GRN] - 1)/2) / (nb_cols[GRN] - 1);
  284.         grnvals[j] = g;
  285.         for(k = 0; k < nb_cols[BLU]; ++k) { 
  286.         int b = (k * 15 + (nb_cols[BLU] - 1)/2) / (nb_cols[BLU] - 1);
  287.         int result;
  288.         bluvals[k] = b;
  289.         result = allocfunc(r, g, b, map + l);
  290.         l++;
  291.         }
  292.     }
  293.     }
  294.     fprintf(stderr, "%d color(s) lost\n",maxcol - l);
  295.  
  296.     /*
  297.      * for each component compute the mapping
  298.      */
  299.     {
  300.     int r;
  301.     for(r=0; r<16; ++r) {
  302.         int g;
  303.         for(g=0; g<16; ++g) {
  304.         int b;
  305.         for(b=0; b<16; ++b) {
  306.             int rederr = 0, grnerr = 0, bluerr = 0;
  307.             int rgb = (r<<8) | (g<<4) | b;
  308.  
  309.             for(i=0;i<4;++i) for(j=0;j<4;++j) {
  310.             int d = dither[i][j];
  311.             int cr, cg, cb, k, q;
  312. #if 0 /* Slightly different algorithm. Needs some tuning. */
  313.             k  = nb_cols[RED]-1;
  314.             cr = r * k / 15;
  315.             q  = r * k - 15*cr;
  316.             if (cr < 0) cr = 0;
  317.             else
  318.                 if(q / k > d / k && rederr <= 0) ++cr;
  319.             if (cr > k) cr = k;
  320.             rederr += redvals[cr]-r;
  321.           
  322.             k  = nb_cols[GRN]-1;
  323.             cg = g * k / 15;
  324.             q  = g * k - 15*cg;
  325.             if (cg < 0) cg = 0;
  326.             else
  327.                 if (q / k > d / k && grnerr <= 0) ++cg;
  328.             if (cg > k) cg = k;
  329.             grnerr += grnvals[cg]-g;
  330.  
  331.             k  = nb_cols[BLU]-1;
  332.             cb = b * k / 15;
  333.             q  = b * k - 15*cb;
  334.             if (cb < 0) cb = 0;
  335.             else
  336.                 if (q / k > d / k && bluerr <= 0) ++cb;
  337.             if (cb > k) cb = k;
  338.             bluerr += bluvals[cb]-b;
  339. #else
  340.             k  = nb_cols[RED]-1;
  341.             cr = r * k / 15;
  342.             q  = r * k - 15*cr;
  343.             if (cr < 0) cr = 0;
  344.             else
  345.                 if(q / k > d / k) ++cr;
  346.             if (cr > k) cr = k;
  347.           
  348.             k  = nb_cols[GRN]-1;
  349.             cg = g * k / 15;
  350.             q  = g * k - 15*cg;
  351.             if (cg < 0) cg = 0;
  352.             else
  353.                 if (q / k > d / k) ++cg;
  354.             if (cg > k) cg = k;
  355.  
  356.             k  = nb_cols[BLU]-1;
  357.             cb = b * k / 15;
  358.             q  = b * k - 15*cb;
  359.             if (cb < 0) cb = 0;
  360.             else
  361.                 if (q / k > d / k) ++cb;
  362.             if (cb > k) cb = k;
  363. #endif
  364.             cidx[i][rgb + (j+4)*4096] = cidx[i][rgb + j*4096] = map[(cr*nb_cols[GRN]+cg)*nb_cols[BLU]+cb];
  365.             }
  366.         }
  367.         }
  368.     }
  369.     }
  370.     free (map);
  371. }
  372.  
  373. #ifndef X86_ASSEMBLY
  374. /*
  375.  * Dither the line.
  376.  * Make sure you call this only with (len & 3) == 0, or you'll just make
  377.  * yourself unhappy.
  378.  */
  379.  
  380. void DitherLine(UBYTE *l, UWORD *r4g4b4, int x, int y, UWORD len, int bits)
  381. {
  382.     UBYTE *dith = cidx[y&3]+(x&3)*4096;
  383.     UBYTE d = 0;
  384.     int bitsleft = 8;
  385.     
  386.     while(len) {
  387.     int v;
  388.     v = dith[0*4096 + *r4g4b4++];
  389.     bitsleft -= bits;
  390.     d |= (v << bitsleft);
  391.     if (!bitsleft)
  392.         *l++ = d, bitsleft = 8, d = 0;
  393.     
  394.     v = dith[1*4096 + *r4g4b4++];
  395.     bitsleft -= bits;
  396.     d |= (v << bitsleft);
  397.     if (!bitsleft)
  398.         *l++ = d, bitsleft = 8, d = 0;
  399.     
  400.     v = dith[2*4096 + *r4g4b4++];
  401.     bitsleft -= bits;
  402.     d |= (v << bitsleft);
  403.     if (!bitsleft)
  404.         *l++ = d, bitsleft = 8, d = 0;
  405.     
  406.     v = dith[3*4096 + *r4g4b4++];
  407.     bitsleft -= bits;
  408.     d |= (v << bitsleft);
  409.     if (!bitsleft)
  410.         *l++ = d, bitsleft = 8, d = 0;
  411.     len -= 4;
  412.     }
  413. }
  414. #endif
  415.